import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { DeleteResult, Not, Repository, UpdateResult } from 'typeorm';
import { RoleType } from '../constants/role.constant';
import { RoleEntity } from '../entities/role.entity';

@Injectable()
export class RoleService {
  constructor(@InjectRepository(RoleEntity) private readonly roleRepository: Repository<RoleEntity>) {}

  /**
   * 创建角色
   * @param name 角色名称
   * @param guards 权限列表
   * @param guardUuidList 权限Uuid列表
   */
  async create(name: string, guardUuidList: string[], description?: string, type?: RoleType): Promise<RoleEntity> {
    const role = new RoleEntity();
    role.name = name;
    role.guardUuidList = guardUuidList;
    role.description = description;
    role.type = type ? type : RoleType.custom;

    return this.roleRepository.save(role);
  }

  /**
   * 删除角色信息
   * @param uuid 角色Uuid
   */
  async delete(uuid: string): Promise<DeleteResult> {
    return this.roleRepository.delete(uuid);
  }

  /**
   * 更新用户角色对应的权限列表
   * @param uuid 角色Uuid
   * @param name 角色名称
   * @param description 角色描述
   * @param guardUuidList 权限Uuid列表
   */
  async update(uuid: string, name?: string, description?: string, guardUuidList?: string[]): Promise<UpdateResult> {
    return this.roleRepository.update(uuid, Object.assign({}, name ? { name } : {}, description ? { description } : {}, guardUuidList ? { guardUuidList } : {}));
  }

  /**
   * 根据角色Uuid获取角色信息
   * @param uuid 角色Uuid
   */
  async findOneByUuid(uuid: string): Promise<RoleEntity> {
    return this.roleRepository.findOne(uuid);
  }

  /**
   * 获取角色信息
   * @param name 角色名称
   */
  async findOneByName(name: string): Promise<RoleEntity> {
    return this.roleRepository
      .createQueryBuilder('roles')
      .leftJoinAndMapMany('roles.guardList', 'guards', 'guards', 'guards.uuid = ANY(roles.guardUuidList)')
      .where('roles.name=:name', { name })
      .getOne();
  }

  /**
   * 检查重名
   * @param name 名称
   * @param uuid 编号
   */
  async checkDuplicateByName(name: string, uuid?: string): Promise<number> {
    if (uuid) return this.roleRepository.count({ uuid: Not(uuid), name: name });
    else return this.roleRepository.count({ name: name });
  }

  /**
   * 根据角色获取权限列表
   * @param uuid 角色uuid
   */
  async findGuardListByRole(uuid: string): Promise<RoleEntity> {
    return this.roleRepository
      .createQueryBuilder('roles')
      .leftJoinAndMapMany('roles.guardList', 'guards', 'guards', 'roles.guardUuidList @> ARRAY[guards.uuid]')
      .where('roles.uuid = :uuid', { uuid })
      .getOne();
  }

  /**
   * 获取所有角色
   */
  async find(): Promise<RoleEntity[]> {
    return this.roleRepository
      .createQueryBuilder('roles')
      .leftJoinAndMapMany('roles.guardList', 'guards', 'guards', 'roles.guardUuidList @> ARRAY[guards.uuid]')
      .orderBy('roles.createdAt', 'DESC')
      .getMany();
  }
}
